﻿
Imports System.Net.Sockets
Imports osi.root.utils
Imports osi.root.procedure
Imports osi.root.connector
Imports osi.root.formation
Imports osi.root.envs
Imports osi.service.tcp.powerpoint

'public for test, do not try to use it directly
Public Class closer
    Private Shared Sub watch_expiration(ByVal p As powerpoint)
        assert(Not p Is Nothing)
        'do not shutdown outgoing connections, since we need to generate it again
        '2014 Apr. 15th
        'to make sure the connection is alive, sometime we need to shutdown and regenerate the connection
        If p.max_lifetime_ms >= 0 Then
            begin_lifetime_event_comb(AddressOf p.expired,
                                      Function() As Boolean
                                          Dim c As connection = Nothing
                                          Dim exp As Boolean = True
                                          While exp AndAlso p.get(c)
                                              exp = nowadays.milliseconds() - c.last_refer_ms() >= p.max_lifetime_ms
                                              If exp Then
                                                  If tcp_trace Then
                                                      raise_error("shutdown a connection ",
                                                                  p.identity(),
                                                                  ", because of expiration, ",
                                                                  "max_lifetime_ms = ",
                                                                  p.max_lifetime_ms,
                                                                  ", now - last_refer_ms = ",
                                                                  nowadays.milliseconds() - c.last_refer_ms())
                                                  End If
                                                  c.no_refer_client().shutdown()
                                              End If
                                              p.release(c)
                                          End While
                                          Return waitfor(min(constants.interval_ms.watch_expiration,
                                                             p.max_lifetime_ms))
                                      End Function)
        End If
    End Sub

    Private Shared Sub watch_connectivity(ByVal p As powerpoint)
        assert(Not p Is Nothing)
        begin_lifetime_event_comb(AddressOf p.expired,
                                  Function() As Boolean
                                      Dim c As connection = Nothing
                                      Dim ec As event_comb = Nothing
                                      Dim cc As Int32 = 0
                                      cc = p.free_count()
                                      While cc > 0 AndAlso p.get(c)
                                          cc -= 1
                                          c.no_refer_client().free_poll_alive(p)
                                          p.release(c)
                                      End While
                                      Return waitfor(constants.interval_ms.watch_connectivity)
                                  End Function)
    End Sub

    Private Shared Sub watch_free(ByVal p As powerpoint)
        watch_expiration(p)
        watch_connectivity(p)
    End Sub

    Private Shared Sub watch_all(ByVal p As powerpoint)
        assert(Not p Is Nothing)
        Dim q As qless2(Of TcpClient) = Nothing
        q = New qless2(Of TcpClient)()
        AddHandler p.connection_generated,
                   Sub(x As TcpClient)
                       q.push(x)
                   End Sub
        assert(stopwatch.repeat(constants.interval_ms.closer_all_poll_alive,
                                Function() As Boolean
                                    Dim cc As Int64 = 0
                                    cc = q.size()
                                    Dim c As TcpClient = Nothing
                                    While cc > 0
                                        assert(q.pop(c) AndAlso Not c Is Nothing)
                                        If c.alive() Then
                                            q.push(c)
                                        End If
                                        cc -= 1
                                    End While
                                    Return Not p.expired()
                                End Function))
        AddHandler p.closing,
                   Sub()
                       Dim c As TcpClient = Nothing
                       While q.pop(c)
                           If tcp_trace Then
                               raise_error("shutdown a connection ",
                                           p.identity(),
                                           ", because the assosiated powerpoint has been close")
                           End If
                           c.shutdown()
                       End While
                   End Sub
    End Sub

    Public Shared Sub watch(ByVal p As powerpoint)
        watch_free(p)
        watch_all(p)
    End Sub
End Class
